package com.touch.jgloo.owt;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Vector;

import com.touch.graphics.Point3D;
import com.touch.graphics.Renderable;
import com.touch.graphics.Repositionable;
import com.touch.graphics.Resizable;
import com.touch.jgloo.core.*;
/*
 * Copyright (c) 2009, TOD Productions All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *	- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *	- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *	-Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
/**
 * A JGLComponent is the simplest form that define JGLComponents. 
 * It defines the shared methods between JGLComponents and allows them to be compatible.
 * @author Homicidal Monkey
 * @version 10.1.9
 * @since r419
 * @see com/touch/Licence
 */
public abstract class JGLComponent extends JGLBase implements Renderable, JGLCompilable, Repositionable, Resizable, MouseListener, Cloneable
{	
	public static JGLTextType TEXT_TYPE = JGLTextType.STROKE;
	//total number of components
	private static int componentCount = 0;
	//component selected
	private static int selected = 0;	
	//index of the JGLComponent
	private final int index;
	//position of the JGLComponent
	private final Point3D position;
	//position of the parent JGLComponent
	private final Point3D parentPosition;
	//size of the JGLComponent
	private final Point3D size;
	//visible state of the JGLComponent
	private boolean visible = true;
	//MouseListeners to send the events to	
	private final Vector <MouseListener> mouseListeners = new Vector <MouseListener>();
	
	/**
	 * Returns the selected component
	 * @return Index of the selected component
	 * @since r461
	 */
	public static final int getSelected()
	{
		//return the selected Component's index
		return selected;
	}
	/**
	 * Sets the selected component
	 * @param component Component to select
	 * @since r461
	 */
	public static final void setSelected(final JGLComponent component)
	{
		//sets the selected component
		selected = component.getIndex();
	}	
	/**
	 * Constructs a JGLComponent and allocates an index as well as increases the total number of components.
	 * @since r461
	 */
	public JGLComponent()
	{
		//increase the componentCount
		//0 is treated as null in this case
		componentCount ++;
		//set the index of this JGLComponent to the current component number
		this.index 		= componentCount;
		//create the size object of the JGLComponent
		this.size 		= new Point3D();
		//create the position object of the JGLComponent
		this.position 	= new Point3D();
		//create the parentPosition object of the JGLComponent
		this.parentPosition = new Point3D();				
	}	
	/**
	 * Returns the index of the component
	 * @return Component's index
	 * @since r461
	 */
	public final int getIndex()
	{
		//returns the component's index
		return this.index;
	}
	/**
	 * Returns whether or not the component is visible. Default is true.
	 * @return Boolean value representing the visible state.
	 * @since r461
	 */
	public final boolean isVisible()
	{		
		//return whether the Component is visible or not
		return visible;
	}
	/**
	 * Sets the visibility state of the component. If a component is not visible, its child components will also not be visible.
	 * @param visible Boolean value representing the visible state.
	 * @since r461
	 */
	public void setVisible(final boolean visible)
	{
		//set the Component as being visible
		this.visible = visible;
	}
	/**
	 * Sets the position of the JGLComponent
 	 * @param x X-Position of the component
	 * @param y Y-Position of the component
	 * @param z Z-Position of the component
	 * @since r461
	 */
	public final void setPosition(final int x, final int y, final int z)
	{	
		//update the x-position
		this.position.x = x;
		//update the y-position
		this.position.y = y;
		//update the z-position
		this.position.z = z;
		//call the sub-class's method for repositioning
		repositioned(x, y, z);
	}	
	/**
	 * Returns the position of the JGLComponent
	 * @return JGLPoint representing the JGLComponent's position
	 * @since r461
	 */
	public final Point3D getPosition()
	{
		//return the position
		return this.position;
	}
	/**
	 * Returns the size of the JGLComponent.
	 * @return JGLPoint representing the size of the Object
	 * @since r461
	 */
	public final Point3D getSize()
	{
		//return the size
		return this.size;
	}
	/**
	 * Return the x-position of the component
	 * @return float value of the JGLComponent's x-position
	 * @since r461
	 */
	public final int getPositionX()
	{
		//return the float value of the component's x-position
		return this.position.x;
	}
	/**
	 * Return the y-position of the component
	 * @return float value of the JGLComponent's y-position
	 * @since r461
	 */
	public final int getPositionY()
	{
		//return the float value of the component's y-position
		return this.position.y;
	}
	/**
	 * Returns the z-position of the component
	 * @return float value of the component's z-position
	 * @since r461
	 */
	public final int getPositionZ()
	{
		//return the float value of the component's z-position
		return this.position.z;
	}
	/**
	 * Returns the width of the JGLComponent
	 * @return float value representing the JGLComponent's width
	 * @since r461
	 */
	public final int getWidth()
	{
		//return the width value
		return this.size.x;
	}
	/**
	 * Returns the height of the JGLComponent
	 * @return float value representing the height of the  JGLComponent
	 * @since r461
	 */
	public final  int getHeight()
	{
		//return the float value representing the height
		return this.size.y;
	}
	/**
	 * Returns the position of the JGLCompnent's parent component
	 * @return JGLPoint representing the position of the JGLComponent's parent's position
	 * @since r461
	 */
	public final  Point3D getParentPosition()
	{
		//return the parent's position
		return this.parentPosition;
	}
	/**
	 * Sets the position of the JGLComponent's parent component
	 * @param x x-position of the parent 
	 * @param y y-position of the parent
	 * @param z z-position of the parent
	 * @since r461
	 */
	protected final  void setParentPosition(final int x, final int y, final int z)
	{		
		//set the x-position
		this.parentPosition.x = x;
		//set the y-position
		this.parentPosition.y = y;
		//set the z-position
		this.parentPosition.z = z;
	}	
	/**
	 * Set the size of the JGLComponent
	 * @param w width of the JGLComponent
	 * @param h height of the JGLComponent
	 * @since r461
	 */
	public final  void setSize(final int w, final int h)
	{
		//set the width of the JGLComponent
		this.size.x = w;
		//set the height of the JGLComponent
		this.size.y = h;
		//call the sub-class's method for setting the size
		resized(w, h);
	}
	/**
	 * Adds a StyleSheet to the Component. StyleSheets are used to customize the look and feel of the object.
	 * @param ss Stylesheet to apply
	 * @since r461
	 */
	public abstract void applyStyleSheet(final JGLStyleSheet ss);
	
	public void mouseClicked(final MouseEvent e)
	{		
		//determine if the component is visible
		if(this.isVisible() == false)
			//if it isn't visible, then don't process the events
			return;
		//set x to the position of where the event occurred 
		final int x = e.getX() - (int)this.getParentPosition().x;
		//set y to the position of where the event occurred
		final int y = e.getY() - (int)this.getParentPosition().y;
		//get the position of the object
		final Point3D position = this.getPosition();
		//get the size of the object
		final Point3D size = this.getSize();
		
		//determine if the button was clicked
		if(x > position.x && x < (position.x + size.x) && y > position.y && y < (position.y + size.y))
		{
			//set this as being selected
			setSelected(this);
			//just pipe the event to another listener
			for(int i = 0; i < this.mouseListeners.size(); i++)
				this.mouseListeners.elementAt(i).mouseClicked(e);			
		}
	}
	
	public void mousePressed(MouseEvent e) {}
	
	public void mouseReleased(MouseEvent e) {}
	
	public void mouseEntered(final MouseEvent e) 	{}
	
	public void mouseExited(final MouseEvent e)		{}
	/**
	 * Add a mouse listener. This will launch a specific event if the object is clicked
	 * @param mListener adds a mouse listener to the JGLComponent.
	 * @since r461
	 */
	public void addMouseListener(final MouseListener mListener)
	{
		//add the listener to the vector of listeners.
		mouseListeners.add(mListener);
	}			
}
